﻿using System.Collections.Generic;

namespace ZFramework.Runtime
{
    public class SceneMgr : FrameworkManagerBase
    {
        private List<string> _loadedScenePaths;
        private List<string> _loadingScenePaths;
        private List<string> _unloadingScenePaths;
        private LoadSceneCallbacks _loadSceneCallbacks;
        private UnloadSceneCallbacks _unloadSceneCallbacks;
        private IResourceMgr _resourceMgr;
        private IEventManager _eventMgr;

        protected override void Awake()
        {
            base.Awake();
            _loadedScenePaths = new List<string>();
            _loadingScenePaths = new List<string>();
            _unloadingScenePaths = new List<string>();
            _loadSceneCallbacks = new LoadSceneCallbacks(LoadSceneSuccessCallback, LoadSceneFailureCallback);
            _unloadSceneCallbacks = new UnloadSceneCallbacks(UnloadSceneSuccessCallback, UnloadSceneFailureCallback);
        }

        void Start()
        {
            _eventMgr = FrameworkManagerManager.GetManager<EventManager>();
            if (_eventMgr == null)
            {
                Log.Error("EventMgr is invalid.");
                return;
            }
            _resourceMgr = FrameworkManagerManager.GetManager<YooResourceMgr>();
            if (_resourceMgr == null)
            {
                Log.Error("YooResourceMgr is invalid.");
                return;
            }
        }

        public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
        }

        public override void Shutdown()
        {
        }

        public void SetEventMgr(IEventManager eventMgr)
        {
            _eventMgr = eventMgr;
        }

        public void SetResourceMgr(IResourceMgr resourceMgr)
        {
            _resourceMgr = resourceMgr;
        }

        public void LoadScene(string sceneAssetName, object userData = null)
        {
            if (SceneIsLoading(sceneAssetName))
            {
                Log.Error("LoadScene 场景正在加载中，请勿重复加载 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            if (SceneIsUnloading(sceneAssetName))
            {
                Log.Error("LoadScene 场景正在卸载中，请检查 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            if (SceneIsLoaded(sceneAssetName))
            {
                Log.Error("LoadScene 场景已加载，请检查 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            _loadingScenePaths.Add(sceneAssetName);
            _resourceMgr.LoadSceneAsync(sceneAssetName, _loadSceneCallbacks, userData);
        }

        public void UnlLoadScene(string sceneAssetName, object userData = null)
        {
            if (SceneIsLoading(sceneAssetName))
            {
                Log.Error("UnlLoadScene 场景正在加载中，请检查 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            if (SceneIsUnloading(sceneAssetName))
            {
                Log.Error("UnlLoadScene 场景正在卸载中，请检查 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            if (!SceneIsLoaded(sceneAssetName))
            {
                Log.Error("UnlLoadScene 场景未加载，请检查 sceneAssetName=={0}", sceneAssetName);
                return;
            }

            _unloadingScenePaths.Add(sceneAssetName);
            _resourceMgr.UnloadScene(sceneAssetName, _unloadSceneCallbacks, userData);
        }

        private void LoadSceneSuccessCallback(string assetName, float duration, object userData)
        {
            _loadingScenePaths.Remove(assetName);
            _loadedScenePaths.Add(assetName);
            _eventMgr.Fire(this, LoadSceneSuccessEventArgs.Create(assetName, duration, userData));
        }

        private void LoadSceneFailureCallback(string assetName, object userData)
        {
            _loadingScenePaths.Remove(assetName);
            _eventMgr.Fire(this, LoadSceneFailureEventArgs.Create(assetName, userData));
        }

        private void UnloadSceneSuccessCallback(string assetName, object userData)
        {
            _unloadingScenePaths.Remove(assetName);
            _loadedScenePaths.Remove(assetName);
            _eventMgr.Fire(this, UnloadSceneSuccessEventArgs.Create(assetName, userData));
        }

        private void UnloadSceneFailureCallback(string assetName, object userData)
        {
            _unloadingScenePaths.Remove(assetName);
            _eventMgr.Fire(this, UnloadSceneFailureEventArgs.Create(assetName, userData));
        }

        public bool SceneIsLoading(string sceneName)
        {
            if (_loadingScenePaths.Contains(sceneName))
            {
                return true;
            }

            return false;
        }

        public bool SceneIsUnloading(string sceneName)
        {
            if (_unloadingScenePaths.Contains(sceneName))
            {
                return true;
            }

            return false;
        }

        public bool SceneIsLoaded(string sceneName)
        {
            if (_loadedScenePaths.Contains(sceneName))
            {
                return true;
            }

            return false;
        }

        public string[] GetAllLoadedSceneNames()
        {
            return _loadedScenePaths.ToArray();
        }
    }
}
